package org.example.demo1.service;


import lombok.extern.slf4j.Slf4j;
import org.example.demo1.dto.*;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class SmartTerminalService {

    @Autowired
    @Qualifier("toolClient")
    private ChatClient toolChatClient;

    @Autowired
    @Qualifier("chatClient")
    private ChatClient chatClient;

    @Autowired
    private ChatMemory chatMemory;

    private static final String COMMAND_PARSE_PROMPT = """
    你是一个Kubernetes运维专家，请将用户的自然语言需求转换为准确的kubectl命令。
        
    当前环境信息：
    - 集群: %s
    - 命名空间: %s

    用户需求: %s
        
    重要规则：
    1. 只返回一个可执行的kubectl命令，不要包含任何解释文字
    2. 命令必须以kubectl开头
    3. 如果涉及命名空间，使用 -n %s
    4. 如果无法理解用户需求，返回：kubectl get pods
        
    示例：
    用户输入："查看所有pod" 
    返回：kubectl get pods -n %s
        
    现在请为以下需求生成kubectl命令：
    """;

    /**
     * 解析自然语言为kubectl命令
     */
    public CommandParseResult parseNaturalLanguage(String userInput, String cluster, String namespace) {
        try {
            // 输入验证
            if (userInput == null || userInput.trim().isEmpty()) {
                return CommandParseResult.error("用户输入不能为空");
            }

            // 使用SpringAI解析自然语言
            String prompt = String.format(COMMAND_PARSE_PROMPT, cluster, namespace, userInput, namespace, namespace);

            String response = toolChatClient.prompt()
                    .user(prompt)
                    .call()
                    .content();

            log.info("AI原始响应: {}", response);

            // 清理和验证命令
            String command = cleanCommand(response);
            log.info("清理后的命令: {}", command);

            // 验证命令安全性
            validateCommandSafety(command);

            CommandRiskLevel riskLevel = assessRiskLevel(command);

            return CommandParseResult.builder()
                    .success(true)
                    .command(command)
                    .description(getCommandDescription(command))
                    .riskLevel(riskLevel)
                    .originalInput(userInput)
                    .build();

        } catch (Exception e) {
            log.error("AI解析命令失败: userInput={}, error={}", userInput, e.getMessage());
            return CommandParseResult.error("智能解析失败: " + e.getMessage());
        }
    }
    /**
     * 执行kubectl命令
     */
    public CommandExecutionResult executeCommand(String command, String cluster, String namespace) {
        try {
            // 再次验证命令安全性
            validateCommandSafety(command);

            // 构建完整的命令
            String fullCommand = buildFullCommand(command, cluster, namespace);

            // 执行命令
            ProcessBuilder pb = new ProcessBuilder();
            pb.command(fullCommand.split("\\s+"));
            pb.directory(new java.io.File(System.getProperty("user.home")));

            Process process = pb.start();

            // 读取输出
            StringBuilder output = new StringBuilder();
            StringBuilder errorOutput = new StringBuilder();

            // 读取标准输出
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    output.append(line).append("\n");
                }
            }

            // 读取错误输出
            try (BufferedReader errorReader = new BufferedReader(
                    new InputStreamReader(process.getErrorStream()))) {
                String line;
                while ((line = errorReader.readLine()) != null) {
                    errorOutput.append(line).append("\n");
                }
            }

            // 等待进程完成
            boolean finished = process.waitFor(30, TimeUnit.SECONDS);
            if (!finished) {
                process.destroyForcibly();
                throw new RuntimeException("命令执行超时");
            }

            int exitCode = process.exitValue();

            if (exitCode == 0) {
                return CommandExecutionResult.builder()
                        .success(true)
                        .output(output.toString().trim())
                        .exitCode(exitCode)
                        .executionTime(System.currentTimeMillis())
                        .build();
            } else {
                String errorMsg = errorOutput.toString().trim();
                if (errorMsg.isEmpty()) {
                    errorMsg = "命令执行失败，退出码: " + exitCode;
                }
                return CommandExecutionResult.error(errorMsg);
            }

        } catch (Exception e) {
            log.error("命令执行失败: {}", e.getMessage());
            return CommandExecutionResult.error("执行失败: " + e.getMessage());
        }
    }

    /**
     * 清理命令
     */
    private String cleanCommand(String response) {
        if (response == null || response.trim().isEmpty()) {
            throw new IllegalArgumentException("AI返回的响应为空");
        }

        // 移除可能的代码块标记
        response = response.replaceAll("```[\\w]*\\n?", "").replaceAll("\\n?```", "");

        // 按行分割，找到以kubectl开头的行
        String[] lines = response.split("\n");
        String command = null;

        for (String line : lines) {
            line = line.trim();
            if (line.startsWith("kubectl")) {
                command = line;
                break;
            }
        }

        // 如果没有找到kubectl命令，尝试从第一行提取
        if (command == null) {
            String firstLine = lines[0].trim();
            if (firstLine.toLowerCase().contains("kubectl")) {
                // 提取kubectl相关部分
                int kubectlIndex = firstLine.toLowerCase().indexOf("kubectl");
                command = firstLine.substring(kubectlIndex);
            } else {
                // 如果完全无法识别，返回默认命令
                log.warn("AI返回的响应无法识别为kubectl命令: {}", response);
                throw new IllegalArgumentException("AI返回的响应不是有效的kubectl命令");
            }
        }

        // 清理命令
        command = command.replaceAll("\\s+", " ").trim();

        log.debug("AI原始响应: {}", response);
        log.debug("清理后的命令: {}", command);


        return command;
    }


    /**
     * 验证命令安全性
     */
    private void validateCommandSafety(String command) {
        if (command == null || command.trim().isEmpty()) {
            throw new SecurityException("命令不能为空");
        }

        String[] parts = command.toLowerCase().split("\\s+");
        if (parts.length < 2) {
            throw new SecurityException("无效的kubectl命令");
        }

        // 检查是否是kubectl命令
        if (!"kubectl".equals(parts[0])) {
            throw new SecurityException("只允许执行kubectl命令");
        }

        // 允许的kubectl子命令
        Set<String> allowedSubCommands = Set.of(
                "get", "describe", "logs", "exec", "port-forward",
                "top", "explain", "api-resources", "api-versions",
                "version", "cluster-info", "config"
        );

        if (parts.length > 1 && !allowedSubCommands.contains(parts[1])) {
            // 对于一些修改操作，需要特别谨慎
            Set<String> moderateRiskCommands = Set.of("apply", "create", "patch", "scale", "annotate", "label");
            Set<String> highRiskCommands = Set.of("delete", "replace", "rollout");

            if (highRiskCommands.contains(parts[1])) {
                throw new SecurityException("不允许执行高风险命令: " + parts[1]);
            }

            if (!moderateRiskCommands.contains(parts[1])) {
                throw new SecurityException("不允许的kubectl命令: " + parts[1]);
            }
        }

        // 检查危险参数
        String commandLower = command.toLowerCase();
        List<String> dangerousFlags = Arrays.asList(
                "--force", "--grace-period=0", "--cascade=foreground",
                "--all", "--all-namespaces", "--delete-now"
        );

        for (String flag : dangerousFlags) {
            if (commandLower.contains(flag)) {
                throw new SecurityException("命令包含危险参数: " + flag);
            }
        }
    }

    /**
     * 评估命令风险等级
     */
    private CommandRiskLevel assessRiskLevel(String command) {
        String[] parts = command.toLowerCase().split("\\s+");

        if (parts.length < 2) {
            return CommandRiskLevel.HIGH;
        }

        String subCommand = parts[1];

        // 低风险：只读操作
        Set<String> lowRiskCommands = Set.of(
                "get", "describe", "logs", "explain", "top",
                "version", "cluster-info", "api-resources", "api-versions"
        );

        if (lowRiskCommands.contains(subCommand)) {
            return CommandRiskLevel.LOW;
        }

        // 中等风险：修改操作但相对安全
        Set<String> mediumRiskCommands = Set.of(
                "apply", "create", "patch", "scale", "annotate", "label", "exec", "port-forward"
        );

        if (mediumRiskCommands.contains(subCommand)) {
            return CommandRiskLevel.MEDIUM;
        }

        return CommandRiskLevel.HIGH;
    }

    /**
     * 获取命令描述
     */
    private String getCommandDescription(String command) {
        String[] parts = command.split("\\s+");
        if (parts.length < 2) {
            return "执行kubectl命令";
        }

        String subCommand = parts[1];
        Map<String, String> descriptions = Map.of(
                "get", "获取资源信息",
                "describe", "查看资源详细信息",
                "logs", "查看Pod日志",
                "exec", "在Pod中执行命令",
                "apply", "应用配置文件",
                "create", "创建资源",
                "delete", "删除资源",
                "scale", "扩缩容资源"
        );

        return descriptions.getOrDefault(subCommand, "执行kubectl " + subCommand + "命令");
    }

    /**
     * 构建完整命令
     */
    private String buildFullCommand(String command, String cluster, String namespace) {
        // 这里可以根据实际环境配置kubectl context等
        // 目前简化处理，直接返回原命令

        // 如果命令中没有指定命名空间，且不是全局资源查询，则添加命名空间
        if (!command.contains("-n ") && !command.contains("--namespace")
                && !command.contains("--all-namespaces")
                && namespace != null && !namespace.isEmpty() && !"default".equals(namespace)) {

            // 在适当位置插入命名空间参数
            String[] parts = command.split("\\s+", 3);
            if (parts.length >= 2) {
                if (parts.length == 2) {
                    command = parts[0] + " " + parts[1] + " -n " + namespace;
                } else {
                    command = parts[0] + " " + parts[1] + " -n " + namespace + " " + parts[2];
                }
            }
        }

        return command;
    }

    /**
     * 获取可用集群列表
     */
    public List<ClusterInfo> getAvailableClusters() {
        // 这里应该从实际的集群配置中获取，目前返回模拟数据
        return Arrays.asList(
                new ClusterInfo("local", "本地集群", "运行中"),
                new ClusterInfo("test", "测试集群", "运行中"),
                new ClusterInfo("prod", "生产集群", "运行中")
        );
    }

    /**
     * 获取命名空间列表
     */
    public List<String> getNamespaces(String cluster) {
        try {
            // 执行kubectl get namespaces获取真实的命名空间列表
            ProcessBuilder pb = new ProcessBuilder("kubectl", "get", "namespaces", "-o", "name");
            Process process = pb.start();

            List<String> namespaces = new ArrayList<>();
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    // 去掉"namespace/"前缀
                    if (line.startsWith("namespace/")) {
                        namespaces.add(line.substring(10));
                    }
                }
            }

            boolean finished = process.waitFor(10, TimeUnit.SECONDS);
            if (finished && process.exitValue() == 0) {
                return namespaces;
            }

        } catch (Exception e) {
            log.warn("获取命名空间列表失败，返回默认列表: {}", e.getMessage());
        }

        // 如果获取失败，返回默认列表
        return Arrays.asList("default", "kube-system", "kube-public", "kube-node-lease");
    }
}
